/**
 * date：2010-11-25
 * author：eason
 * description：树状组件项目类.
 * 
 * 一个项目(也称树状结构中的一个节点,或一条栏目),既可作为子项目出现,也可作为父项目出现.
 * 相对于它的父项目,它作为一个子项目出现;而相对于它的子项目,它作为一个父项目出现.
 * 
 * 因此,该类在设计上(主要是针对计算组件高度)是采用迭代的方式进行的.
 * 即一个项目的组件高度等于其子项目高度之和(而其每个子项目的高度又是各自的子项目的高度决定的);
 * 
 * 当树状结构中任意一个项目发生打开(itemOpen)、关闭(itemClose)事件时,其所有父级项目都会自里向外派发listChanged事件,
 * 从而使整个树状结构作出更新.
 */
package com.pickgliss.ui.controls.tree
{
	import com.pickgliss.events.TreeEvent;
	import com.pickgliss.ui.core.Component;
	
	import flash.display.DisplayObject;
	import flash.display.DisplayObjectContainer;
	import flash.display.InteractiveObject;
	import flash.display.Sprite;
	import flash.events.MouseEvent;
	
	[Event(name="itemSelected",type="com.pickgliss.events.TreeEvent")]
	[Event(name="itemOpen",type="com.pickgliss.events.TreeEvent")]
	[Event(name="itemClose",type="com.pickgliss.events.TreeEvent")]
	
	[Event(name="listChanged",type="com.pickgliss.events.TreeEvent")]
	
	
	public class TreeItem extends Component
	{
	
		private var _data : *;	
		private var _depth : int;
		private var _parent : TreeItem;
		private var _childItems : Vector.<TreeItem>;
		private var _isOpen : Boolean;
		
		/**
		 * 自身高度。通常对应于该项目关闭时的高度（即_selfComponent的高度）。 
		 */		
		private var _selfH : Number;	
		/**
		 * 自身组件。 即独立的栏目组件，不包含其任何子项目。
		 * 必需通过set方法来设置
		 */		
		private var _selfComponent : Component;
		
		private var _totalH : Number;
		
		private var _offsetX : Number = 0;
		
		public function TreeItem()
		{
			super();
				
			_childItems = new Vector.<TreeItem>();
		}
		
		private function addHandler():void
		{
			_selfComponent.addEventListener(MouseEvent.CLICK, onMouseClickHandler);
		}
		private function removeHandler():void
		{
			if(_selfComponent && _selfComponent.hasEventListener(MouseEvent.CLICK)){
				_selfComponent.removeEventListener(MouseEvent.CLICK, onMouseClickHandler);
			}
		}
		/**
		 * 鼠标点击 _selfComponent 时的处理函数.
		 * @param event
		 * 
		 */		
		private function onMouseClickHandler(event : MouseEvent):void
		{
			if(this.hasChildren()){
				if(this.isOpen()){
					close();					
				}else{
					open();
				}
			}else{
				dispatchTreeEvent(TreeEvent.ITEM_SELECTED);
			}
		}
		
		/**
		 * 该项在树状结构中的深度 set 和 get 属性.
		 * 项层项目的深度为0,项层项目下一层的项目的深度为1,以此类推. 
		 */	
		public function get depth():int
		{
			return _depth;
		}
		
		public function set depth(value:int):void
		{
			_depth = value;
		}
		
		
		/**
		 * 获得父级项目. 
		 */	
		public function getParent():TreeItem
		{
			return _parent;
		}
		
		/**
		 * 设置父级项目. 
		 * @param item
		 * 
		 */		
		public function setParent(item:TreeItem):void
		{
			_parent = item;
			_parent.addChildItem(this);//将自已添加到父项目的子集中.
			this.depth = _parent.depth + 1;
		}
		
		
		/**
		 * 获得项目的数据. 
		 */	
		public function getData():*
		{
			return _data;
		}
		/**
		 * 获得项目的数据. 
		 */	
		public function setData(value : *):void
		{
			_data = value;
		}
		
		
		/**
		 * 获得显示对象. 
		 * @return 
		 * 
		 */	
		public function getView():DisplayObjectContainer
		{
			return this;
		}
		
		
		/**
		 * 获得项目的高度. 
		 * Tree组件将使用该方法来定位每个项目的高度,而不是通过getView()的height属性来定位。
		 * @return 
		 * 
		 */		
		public function getHeight():Number
		{
			return _totalH;
		}
		private function refreshHeight():void
		{
			_totalH = _selfH;
			if(_isOpen){
				for(var i : int = 0; i < _childItems.length; i++){
					_totalH += _childItems[i].getHeight();
				}
			}
		}
		
		
		/**
		 * 获得项目的宽度.
		 * Tree组件将使用该方法来定位每个项目的宽度,而不是通过getView()的width属性来定位。
		 * @return 
		 * 
		 */	
		public function getWidth():Number
		{
			return getView().width;
		}
		
		
		/**
		 * 添加一个子项目. 
		 * @param item
		 * 
		 */	
		public function addChildItem(item:TreeItem):void
		{
			_childItems.push(item);
			item.addEventListener(TreeEvent.ITEM_OPEN, onChildItemOpen);
			item.addEventListener(TreeEvent.ITEM_CLOSE, onChildItemClose);
			item.addEventListener(TreeEvent.ITEM_SELECTED, onChildItemSelected);
			item.addEventListener(TreeEvent.LIST_CHANGED, onChildListChanged);
		}	

		private function onChildItemOpen(event:TreeEvent):void
		{
			updateItemsPosition();
			refreshHeight();
			
			dispatchTreeEvent(TreeEvent.LIST_CHANGED)
		}
		private function onChildItemClose(event:TreeEvent):void
		{
			updateItemsPosition();
			refreshHeight();
			
			dispatchTreeEvent(TreeEvent.LIST_CHANGED)
		}
		private function onChildItemSelected(event:TreeEvent):void
		{
			dispatchTreeEvent(TreeEvent.ITEM_SELECTED, event.getItem());
		}
		private function onChildListChanged(event:TreeEvent):void
		{
			updateItemsPosition();
			refreshHeight();
			dispatchTreeEvent(TreeEvent.LIST_CHANGED);
		}
		
		
		
		/**
		 * 移除子项目的侦听函数. 
		 * 
		 */		
		private function removeChildItemsHandler():void
		{
			var item : TreeItem;
			for(var i : int = 0; i < _childItems.length; i++){
				item = _childItems[i];
				
				item.removeEventListener(TreeEvent.ITEM_OPEN, onChildItemOpen);
				item.removeEventListener(TreeEvent.ITEM_CLOSE, onChildItemClose);
				item.removeEventListener(TreeEvent.ITEM_SELECTED, onChildItemSelected);
				item.removeEventListener(TreeEvent.LIST_CHANGED, onChildListChanged);
			}
		}
		
		
		/**
		 * 更新所有子项目的位置. 
		 * 
		 */		
		private function updateItemsPosition():void
		{
			var item : TreeItem;
			_childItems[0].getView().y = _selfH;
			_childItems[0].getView().x = _offsetX;
			for(var i : int = 1; i < _childItems.length; i++){
				item = _childItems[i];
				item.getView().x = _offsetX;
				item.getView().y = _childItems[i - 1].getView().y + _childItems[i - 1].getHeight();
			}
		}
		
		
		/**
		 * 获得该项目的所有子项目. 
		 * @param item
		 * 
		 */	
		public function getChildItems():Vector.<TreeItem>
		{
			return _childItems;
		}
		
		
		/**
		 * 该项目是否拥有子项目.
		 * @return 
		 * 
		 */	
		public function hasChildren():Boolean
		{
			return _childItems.length>0? true:false;
		}
		
		
		/**
		 * 展开项目. 
		 * 
		 */		
		public function open():void
		{			
			_isOpen = true;
			for(var i : int = 0; i < _childItems.length; i++){
				getView().addChild(_childItems[i].getView());
			}
			
			updateItemsPosition();
			refreshHeight();
			
			dispatchTreeEvent(TreeEvent.ITEM_OPEN);			
		}
		
		/**
		 * 关闭项目.
		 * 
		 */		
		public function close():void
		{
			var item : TreeItem;
			
			_isOpen = false;
			for(var i : int = 0; i < _childItems.length; i++){
				getView().removeChild(_childItems[i].getView());
			}
			
			refreshHeight();
			
			dispatchTreeEvent(TreeEvent.ITEM_CLOSE);	
		}
		
		/**
		 * 该项目是否打开. 
		 * @return 
		 * 
		 */	
		public function isOpen():Boolean
		{
			return _isOpen;
		}
		
		private function dispatchTreeEvent(type : String, item : TreeItem = null):void
		{
			if(item == null){
				item = this;
			}
			dispatchEvent(new TreeEvent(type, item));
		}
		
		private function disposeItems():void
		{
			var item : TreeItem;
			
			for(var i : int = 0; i < _childItems.length; i++){
				if(getView().contains(_childItems[i].getView())){
					getView().removeChild(_childItems[i].getView());
				}
				
				_childItems[i].dispose();
				_childItems[i] = null;
			}
		}
		override public function dispose():void
		{
			removeHandler();
			removeChildItemsHandler();
			
			disposeItems();
			
			_parent = null;
			_childItems = null;
			
			super.dispose();
		}
		
		//////////////////////////////////////////////////////////////////////////////////////////
		// 
		//  样式,布局等属性设置
		//
		/////////////////////////////////////////////////////////////////////////////////////////
		
		public function set selfComponent(value : Component):void
		{
			_selfComponent = value;
			
			addChild(_selfComponent);
			
			addHandler();
		}
		public function set offsetX(value : Number):void
		{
			_offsetX = value;
		}
		override public function set height(h:Number):void
		{
			super.height = h;
			
			_selfH = h;
			_totalH = _selfH;
		}
	}
}